package deustotech.mobility.vc.core;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;

import c2x.japi.net.messages.Message;
import c2x.japi.net.messages.MessageListener;
import c2x.japi.net.messages.ipMessages.ipMessage;
import c2x.japi.net.messages.ipMessages.ipMessageParser;
import c2x.japi.net.messages.mgmt.MgmtMessageParser;
import c2x.japi.net.util.NetworkOrderBuffer;
import c2x.japi.threads.SendReceiveThread;

public class ServidorUniCast extends Thread{

	private Controller c;
	private String dir=null;
	private boolean connected;
	private int IPv4Port = 1506;
	private Hashtable<Integer, Long> sender = null;
	private Hashtable<Integer, Long> receiver = null;
	private UnicastListener uL;



	public ServidorUniCast(String dir){
		this.dir = dir;
		InetAddress ip = obtenerIPNodoRemoto(dir);
		if(ip!=null){
			dir = ip.getCanonicalHostName();
		System.out.println("Enviar mensaje a "+dir);
		uL = UnicastListener.getInstance();
		uL.apuntarServidor(this);
		c = Controller.getInstance();
//		try {
//			SRT = new SendReceiveThread(c.getGateway().getHostAddress(), (short)IPv4Port,(short)IPv4Port,new ipMessageParser());
//			SRT.addMessageListener(this);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		setConnected(true);
		}
	}

	private InetAddress obtenerIPNodoRemoto(String dire) {
		String base = dire.replace(".1", "");
		String sub = ".25";
		InetAddress in = null;
		boolean found=false;
		int index=4;
		while(index>0 && !found)
		try {
			 in = InetAddress.getByName(base.concat(sub.concat(""+index)));
			if(in.isReachable(200))
				found = true;
			else{
				index--;
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {	
			e.printStackTrace();
		}
		
		return in;
		
	}

	public void run(){
		sender = new Hashtable<Integer, Long>();
		receiver = new Hashtable<Integer, Long>();
		int enviando = 0;
		while(isConnected()){
			try{
//				sender.put(enviando, System.currentTimeMillis());
				send("100 enviando "+enviando);
				sender.put(enviando, System.currentTimeMillis());
				enviando++;
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}
		uL.terminate();
//		SRT.removeMessageListener(this);
//		SRT.terminate();

	}

	private boolean isConnected() {
		return connected;
	}
	private Hashtable<Integer, Long> getSender(){
		return sender;
	}

	private Hashtable<Integer, Long> getReceiver(){
		return receiver;
	}

	public String getDir() {
		return dir;
	}
	public void setConnected(boolean is){
		connected = is;
	}

	protected void send(String texto) {

		char[] tA = texto.toCharArray();	
		short paylSize = Short.parseShort(tA.length+"");
		NetworkOrderBuffer payload = new NetworkOrderBuffer(paylSize);

		System.out.println("Nuevo Mensaje: ");
		for (int i = 0;i <paylSize;i++){
			byte patternbyte = (byte) tA[i];
			payload.appendByte(patternbyte);
		}
		InetAddress address = null;
		try {
			address = InetAddress.getByName(dir);
		} catch (UnknownHostException e1) {
			System.err.println("Timing.sendIPv4Msg(): Could not send to node " + address);
			e1.printStackTrace();
		}
		DatagramPacket packet = new DatagramPacket(
				payload.getBuffer(), payload.getCapacity(), address, IPv4Port);

		DatagramSocket dsocket = null;

		try {
			dsocket = new DatagramSocket();
		} catch (SocketException e2) {
			System.err.println("Timing.sendIPv4Msg(): Send IPv4: Could not open datagram socket.");
			e2.printStackTrace();
		}

		try {
			dsocket.send(packet);
			dsocket.close();
		} catch (IOException e3) {
			System.err.println("Timing.sendIPv4Msg(): Send IPv4: Could not close datagram socket.");
			e3.printStackTrace();
		}
	}

	public void getJitter(String path){
		if(!receiver.isEmpty()){
			PrintWriter out = null;
		try {
			out = new PrintWriter(new File(path));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		Hashtable<Integer, Long> comp = new Hashtable<Integer, Long>();
		for(int i = 0; i<sender.size(); i++){
			Long compared = sender.get(i)-receiver.get(i);
			if(compared == sender.get(i))
				compared = (long) 0;
			comp.put(i, compared);
			out.println(i + "\t=>\t"+comp.get(i));
		}
		out.println(-1 + "\t=>\t"+getMedia(comp));
		out.close();
		}
	}

	private int getMedia(Hashtable<Integer, Long> comp) {
		int media = 0;
		for(int i =0; i<comp.size();i++)
			media +=comp.get(i);
		return media/comp.size();
	}

	public void addReceived(int num, Long arriveTime) {
		receiver.put(num, arriveTime);
	}
}



